package br.ufpe.abaco.ParserGen.lexer;

class CharManager  implements java.io.Serializable {

    int starts[] = new int[300];
    int ends[] = new int[300];
    int nextFreeEntry = 0;
    int tabSize = 300;

    int lookupTable[] = new int[256];


    /**
     *  Description of the Method
     *
     *@param  pos  Description of the Parameter
     */
    void insertAtPos(int pos) {
        for (int c = nextFreeEntry; c > pos; c--) {
            starts[c] = starts[c - 1];
            ends[c] = ends[c - 1];
        }
        nextFreeEntry++;

    }


    /**
     *  Description of the Method
     *
     *@param  start  Description of the Parameter
     *@param  end    Description of the Parameter
     */
    void insertClass(int start, int end) {
        int pos = 0;

        if (start > end) {
            throw new RuntimeException("Invalid Arguments");
        }

        while (pos < nextFreeEntry && start > ends[pos]) {
            pos++;
        }
        if (pos == nextFreeEntry) {
            starts[nextFreeEntry] = start;
            ends[nextFreeEntry] = end;
            nextFreeEntry++;
            return;
        }

        if (end < starts[pos]) {
            insertAtPos(pos);
            starts[pos] = start;
            ends[pos] = end;
            return;
        }

        if (end > ends[pos]) {
            insertClass(ends[pos] + 1, end);
            end = ends[pos];
        }

        if (start < starts[pos]) {
            insertAtPos(pos);
            starts[pos] = start;
            ends[pos] = starts[pos + 1] - 1;
            start = starts[pos + 1];
            pos++;
        }

        if (starts[pos] == start && ends[pos] == end) {
            ;
        } else {

            if (ends[pos] != end) {
                insertAtPos(pos + 1);
                starts[pos + 1] = end + 1;
                ends[pos + 1] = ends[pos];
                ends[pos] = end;

            }
            if (starts[pos] != start) {
                insertAtPos(pos);
                starts[pos] = starts[pos + 1];
                ends[pos] = start - 1;
                starts[pos + 1] = start;
            }
        }

    }


    /**
     *  Description of the Method
     */
    void compile() {
        int c1;
        int c2;
        for (c1 = 0; c1 < 256; c1++) {
            lookupTable[c1] = -1;
        }
        for (c1 = 0; c1 < nextFreeEntry; c1++) {
            for (c2 = starts[c1]; c2 <= ends[c1]; c2++) {
                lookupTable[c2] = c1;
            }
        }
    }


    /**
     *  Gets the class attribute of the CharManager object
     *
     *@param  v  Description of the Parameter
     *@return    The class value
     */
    int getClass(int v) {
        if (lookupTable[v] == -1) {
            throw new RuntimeException("Lexical Error!!!");
        }
        return lookupTable[v];
    }


    /**
     *  Description of the Method
     *
     *@return    Description of the Return Value
     */
    int size() {
        return nextFreeEntry;
    }


    /**
     *  Description of the Method
     *
     *@param  c  Description of the Parameter
     *@return    Description of the Return Value
     */
    public String printClass(int c) {
        return " [ " + ((char) starts[c]) + "-" + ((char) ends[c]) + " ] ";
    }


    /**
     *  Description of the Method
     *
     *@return    Description of the Return Value
     */
    public String toString() {
        String resul = "";
        for (int c = 0; c < nextFreeEntry; c++) {
            resul += " [ " + ((char) starts[c]) + "-" + ((char) ends[c]) + " ] ";
        }
        return resul;
    }


    /**
     *  Description of the Method
     *
     *@param  args  Description of the Parameter
     */
    static void main(String args[]) {
        CharManager m = new CharManager();

        m.insertClass('0', '9');
        m.insertClass('a', 'z');
        m.insertClass('b', 'b');
        m.insertClass('e', 'e');

        System.out.println(m);

    }

}

